/****************************************************************************
Copyright 2006 Kervin L. Pierre
    EMAIL: otlkcon@adevsoft.com

This file is part of Otlkcon.

Otlkcon is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.

Otlkcon is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Lesser GNU General Public License for more details.

You should have received a copy of the Lesser GNU General Public License
along with Otlkcon; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

*******************************************************************************/

#include "StdAfx.h"

#include "O_ITableView.h"
#include "O_ITable.h"
#include "otlkcon_debug.h"

O_ITableView::O_ITableView(void)
{
    table = NULL;
    parent = NULL;
    cRef = 0;
}

O_ITableView::~O_ITableView(void)
{
    ;
}

STDMETHODIMP O_ITableView::Create(LPMAPITABLE tbl, O_ITable *par)
{
    HRESULT result;

    result = Init(tbl,par);

    return result;
}

STDMETHODIMP O_ITableView::Destroy()
{
    HRESULT result = S_OK;

    return result;
}

STDMETHODIMP O_ITableView::Init(LPMAPITABLE tbl, O_ITable *par)
{
    HRESULT result = S_OK;

    table = tbl;
    parent = par;

    return result;
}

STDMETHODIMP O_ITableView::QueryInterface (REFIID riid, void **ppv)
{
    HRESULT result = S_OK;

    OTLKCON_LOG_PRINTF(OTLKCON_LOG_LEVEL_INFO, OTLKCON_LOG_TARGET_ALL, L"inside O_ITableView->QueryInterface. \
 {%0.8X-%0.4X-%0.4X-%0.2X%0.2X-%0.2X%0.2X%0.2X%0.2X%0.2X%0.2X}\n",
        riid.Data1, riid.Data2, riid.Data3, riid.Data4[0], riid.Data4[1],
        riid.Data4[2], riid.Data4[3], riid.Data4[4], riid.Data4[5],
        riid.Data4[6], riid.Data4[7]);

    *ppv = NULL;

    if( memcmp(&riid, &IID_IUnknown, sizeof(IID)) &&
        memcmp(&riid, &IID_IMAPITable, sizeof(IID)))
    { 
        result = ResultFromScode(E_NOINTERFACE);
        return result;
    }

    OTLKCON_LOG_PRINTF(OTLKCON_LOG_LEVEL_INFO, OTLKCON_LOG_TARGET_ALL, L"inside O_ITableView->QueryInterface. \
 {%0.8X-%0.4X-%0.4X-%0.2X%0.2X-%0.2X%0.2X%0.2X%0.2X%0.2X%0.2X} - Supported\n",
        riid.Data1, riid.Data2, riid.Data3, riid.Data4[0], riid.Data4[1],
        riid.Data4[2], riid.Data4[3], riid.Data4[4], riid.Data4[5],
        riid.Data4[6], riid.Data4[7]);

    AddRef();
    *ppv = (LPVOID)this;

    return result;
}

ULONG STDMETHODCALLTYPE O_ITableView::AddRef (void)
{
    cRef++;
    OTLKCON_LOG_PRINTF(OTLKCON_LOG_LEVEL_INFO,  OTLKCON_LOG_TARGET_ALL, L"O_ITableView::AddRef %d\n",
             cRef);

    return cRef;
}

ULONG STDMETHODCALLTYPE O_ITableView::Release (void)
{
    OTLKCON_LOG_PRINTF(OTLKCON_LOG_LEVEL_INFO,  OTLKCON_LOG_TARGET_ALL, L"O_ITableView::Release %d\n",
            cRef);

    if ( cRef == 1 )
    {
        return 0;
    }

    return --cRef;
}

STDMETHODIMP O_ITableView::GetLastError(HRESULT hResult,
    ULONG ulFlags,
    LPMAPIERROR * lppMAPIError)
{
    HRESULT result;

    result = table->GetLastError( hResult, ulFlags, lppMAPIError );

    return result;
}

STDMETHODIMP O_ITableView::Advise(ULONG ulEventMask,
    LPMAPIADVISESINK lpAdviseSink,
    ULONG * lpulConnection)
{
    HRESULT result;
    ULONG ulConnectionParent = 0, ulConn = 0;

    // Advise() the parent object that this view has been Advise()'ed.
    // This is because view's are read-only and hence never changed, their
    // parents do.
    result = parent->Advise( ulEventMask, lpAdviseSink, &ulConnectionParent );
    result = table->Advise( ulEventMask, lpAdviseSink, &ulConn );

    parentConnections[ulConn] = ulConnectionParent;
    *lpulConnection = ulConn;

    return result;
}

STDMETHODIMP O_ITableView::Unadvise (ULONG ulConnection)
{
    HRESULT result;
    map <ULONG, ULONG> :: const_iterator connIter;
    ULONG ulConnectionParent;
    
    connIter = parentConnections.find( ulConnection );
    if( connIter == parentConnections.end() )
    {
        OTLKCON_DEBUGBREAK
        return E_FAIL;
    }

    ulConnectionParent = connIter->second;

    result = table->Unadvise( ulConnection );
    result = parent->Unadvise( ulConnectionParent );

    return result;
}

STDMETHODIMP O_ITableView::GetStatus (ULONG * lpulTableStatus,
    ULONG * lpulTableType)
{
    HRESULT result;

    result = table->GetStatus( lpulTableStatus, lpulTableType );

    return result;
}

STDMETHODIMP O_ITableView::SetColumns (LPSPropTagArray lpPropTagArray,
    ULONG ulFlags)
{
    HRESULT result;

	TRACE_SPROPTAG_ARRAY(OTLKCON_LOG_TARGET_ALL, lpPropTagArray, L"O_ITableView::SetColumns");
    
	result = parent->SetColumns( lpPropTagArray, ulFlags );
    result = table->SetColumns( lpPropTagArray, ulFlags );

    return result;
}

STDMETHODIMP O_ITableView::QueryColumns (ULONG ulFlags,
    LPSPropTagArray * lppPropTagArray)
{
    HRESULT result;

    result = table->QueryColumns( ulFlags , lppPropTagArray);

	TRACE_SPROPTAG_ARRAY(OTLKCON_LOG_TARGET_ALL, *lppPropTagArray, L"O_ITableView::QueryColumns");
    return result;
}

STDMETHODIMP O_ITableView::GetRowCount (ULONG ulFlags,
    ULONG * lpulCount)
{
    HRESULT result;

    result = table->GetRowCount( ulFlags, lpulCount );

    return result;
}

STDMETHODIMP O_ITableView::SeekRow (BOOKMARK bkOrigin,
    LONG lRowCount,
    LONG * lplRowsSought)
{
    HRESULT result;

    result = table->SeekRow( bkOrigin, lRowCount, lplRowsSought );

    return result;
}

STDMETHODIMP O_ITableView::SeekRowApprox (ULONG ulNumerator,
    ULONG ulDenominator)
{
    HRESULT result;

    result = table->SeekRowApprox( ulNumerator, ulDenominator );

    return result;
}

STDMETHODIMP O_ITableView::QueryPosition (ULONG * lpulRow,
    ULONG * lpulNumerator,
    ULONG * lpulDenominator)
{
    HRESULT result;

    result = table->QueryPosition( lpulRow, lpulNumerator,
                        lpulDenominator );

    return result;
}

STDMETHODIMP O_ITableView::FindRow (LPSRestriction lpRestriction,
    BOOKMARK bkOrigin,
    ULONG ulFlags)
{
    HRESULT result;

    result = table->FindRow( lpRestriction, bkOrigin, ulFlags );

    return result;
}

STDMETHODIMP O_ITableView::Restrict (LPSRestriction lpRestriction,
    ULONG ulFlags)
{
    HRESULT result;

    result = table->Restrict( lpRestriction, ulFlags);

    return result;
}

STDMETHODIMP O_ITableView::CreateBookmark (BOOKMARK * lpbkPosition)
{
    HRESULT result;

    result = table->CreateBookmark( lpbkPosition );

    return result;
}

STDMETHODIMP O_ITableView::FreeBookmark (BOOKMARK bkPosition)
{
    HRESULT result;

    result = table->FreeBookmark( bkPosition );

    return result;
}

STDMETHODIMP O_ITableView::SortTable (LPSSortOrderSet lpSortCriteria,
    ULONG ulFlags)
{
    HRESULT result;

    result = table->SortTable( lpSortCriteria, ulFlags );

    return result;
}

STDMETHODIMP O_ITableView::QuerySortOrder (LPSSortOrderSet * lppSortCriteria)
{
    HRESULT result;

    result = table->QuerySortOrder( lppSortCriteria );

    return result;
}

STDMETHODIMP O_ITableView::QueryRows(LONG lRowCount,
    ULONG ulFlags,
    LPSRowSet * lppRows)
{
    HRESULT result;

    result = table->QueryRows( lRowCount, ulFlags, lppRows );

	TRACE_ROWSET(OTLKCON_LOG_TARGET_ALL, *lppRows, L"O_ITableView::QueryRows");
    
	if( parent->derefAssocObj == 0 || FAILED(result) )
        return result;

//    result = parent->QueryMoreRows( lRowCount, ulFlags, lppRows );

    return result;
}

STDMETHODIMP O_ITableView::Abort()
{
    HRESULT result;

    result = table->Abort();

    return result;
}

STDMETHODIMP O_ITableView::ExpandRow (ULONG cbInstanceKey,
    LPBYTE pbInstanceKey,
    ULONG ulRowCount,
    ULONG ulFlags,
    LPSRowSet * lppRows,
    ULONG * lpulMoreRows)
{
    HRESULT result;

    result = table->ExpandRow( cbInstanceKey, pbInstanceKey, ulRowCount,
                                ulFlags, lppRows, lpulMoreRows );

    return result;
}

STDMETHODIMP O_ITableView::CollapseRow (ULONG cbInstanceKey,
    LPBYTE pbInstanceKey,
    ULONG ulFlags,
    ULONG * lpulRowCount)
{
    HRESULT result;

    result = table->CollapseRow( cbInstanceKey, pbInstanceKey, ulFlags,
                                    lpulRowCount );

    return result;
}

STDMETHODIMP O_ITableView::WaitForCompletion (ULONG ulFlags,
    ULONG ulTimeout,
    ULONG * lpulTableStatus)
{
    HRESULT result;

    result = table->WaitForCompletion( ulFlags, ulTimeout, lpulTableStatus );

    return result;
}

STDMETHODIMP O_ITableView::GetCollapseState (ULONG ulFlags,
    ULONG cbInstanceKey,
    LPBYTE lpbInstanceKey,
    ULONG * lpcbCollapseState,
    LPBYTE * lppbCollapseState)
{
    HRESULT result;

    result = table->GetCollapseState( ulFlags, cbInstanceKey, lpbInstanceKey,
                                          lpcbCollapseState, lppbCollapseState );

    return result;
}

STDMETHODIMP O_ITableView::SetCollapseState (ULONG ulFlags,
    ULONG cbCollapseState,
    LPBYTE pbCollapseState,
    BOOKMARK * lpbkLocation)
{
    HRESULT result;

    result = table->SetCollapseState( ulFlags, cbCollapseState, pbCollapseState,
                                          lpbkLocation );

    return result;
}